home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_xemacs.idb / usr / freeware / lib / xemacs-20.4 / lisp / hm--html-menus / hm--html-indentation.el.z / hm--html-indentation.el
Encoding:
Text File  |  1998-05-21  |  8.6 KB  |  272 lines

  1. ;;; hm--html-indentation.el
  2. ;;; v1.00;  9-Feb-1997
  3. ;;; Copyright (C) 1997 Heiko Muenkel
  4. ;;; email: muenkel@tnt.uni-hannover.de
  5. ;;;
  6. ;;;  This program is free software; you can redistribute it and/or modify
  7. ;;;  it under the terms of the GNU General Public License as published by
  8. ;;;  the Free Software Foundation; either version 1, or (at your option)
  9. ;;;  any later version.
  10. ;;;
  11. ;;;  This program is distributed in the hope that it will be useful,
  12. ;;;  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ;;;  GNU General Public License for more details.
  15. ;;;
  16. ;;;  You should have received a copy of the GNU General Public License
  17. ;;;  along with this program; if not, write to the Free Software
  18. ;;;  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. ;;;
  20. ;;; 
  21. ;;; Description:
  22. ;;;
  23. ;;;    Defines functions for the indentation.
  24. ;;; 
  25. ;;; Installation: 
  26. ;;;   
  27. ;;;    Put this file in one of your load path directories.
  28. ;;;
  29.  
  30. (defun hm--html-point-between-strings-p (string-1
  31.                      string-2
  32.                      &optional boundary)
  33.   "Returns non nil, if the current point is between STRING-1 and STRING-2."
  34.   (when (and (re-search-backward (concat "\\("
  35.                      (regexp-quote string-1)
  36.                      "\\)\\|\\("
  37.                      (regexp-quote string-2)
  38.                      "\\)")
  39.                  boundary
  40.                  t)
  41.          (match-string 1))
  42.     (point)))
  43.  
  44. (defun hm--html-in-comment-p ()
  45.   "Checks if the current point is in a comment block.
  46. If this is the case, then the start point of the comment is returned.
  47. Otherwise nil is returned."
  48.   (save-excursion
  49.     (hm--html-point-between-strings-p comment-start comment-end)))
  50.  
  51. (defun hm--html-previous-line-start ()
  52.   "Returns the start of the previous non blank line."
  53.   (save-excursion
  54.     (beginning-of-line)
  55.     (skip-chars-backward " \t\n")
  56.     (beginning-of-line)
  57.     (point)))
  58.  
  59. (defun hm--html-look-at-comment-end-p ()
  60.   "T, if the current line starts with the comment end."
  61.   (looking-at (regexp-quote comment-end)))
  62.  
  63. (defun hm--html-column-of-previous-regexp (regexp)
  64.   "Returns the column of the start of the previous REGEXP.
  65. It searches backward until the REGEXP is found. If no
  66. REGEXP is found, then it returns 0."
  67.   (save-excursion
  68.     (if (re-search-backward regexp nil t)
  69.     (current-column)
  70.       0)))
  71.  
  72. (defun hm--html-look-at-end-tag-p ()
  73.   "Returns the end tag name if the point is at the start of an end tag.
  74. nil is returned otherwise."
  75.   (when (looking-at "\\(<[ \t\n]*/[ \t\n]*\\)\\([^ \t\n>]+\\)")
  76.     (match-string 2)))
  77.     
  78.  
  79. (defun hm--html-previous-line-indentation ()
  80.   "Returns the indentation of the previous non blank line."
  81.   (save-excursion
  82.     (beginning-of-line)
  83.     (skip-chars-backward " \t\n")
  84.     (back-to-indentation)
  85.     (current-column)))
  86.  
  87. (defun hm--html-in-tag-p ()
  88.   "Checks if the current point is in a tag.
  89. If this is the case, then the start point of the tag is returned.
  90. Otherwise nil is returned."
  91.   (save-excursion
  92.     (let ((start (re-search-backward "\\(<\\)\\|\\(>\\)" nil t)))
  93.       (when (match-string 1)
  94.     start))))
  95.  
  96. (defun hm--html-return-beginning-of-line ()
  97.   "Returns the beginning of the current line."
  98.   (save-excursion
  99.     (beginning-of-line)
  100.     (point)))
  101.  
  102. (defun hm--html-return-end-of-line ()
  103.   "Returns the end of the current line."
  104.   (save-excursion
  105.     (end-of-line)
  106.     (point)))
  107.  
  108. (defun hm--html-paramter-column-in-line-after-point (point)
  109.   "Returns the column where the second non blank text after POINT starts.
  110. This point must be in the line with POINT otherwise it returns nil."
  111.   (save-excursion
  112.     (goto-char point)
  113.     (when (re-search-forward "<[ \t]*[^ \t]+[ \t]"
  114.                  (hm--html-return-end-of-line)
  115.                  t)
  116.       (when (looking-at "[^\n]")
  117.     (current-column)))))
  118.  
  119. (defun hm--html-column-of-point (point)
  120.   "Returns the column of the POINT."
  121.   (save-excursion
  122.     (goto-char point)
  123.     (current-column)))
  124.  
  125. (defun hm--html-search-previous-tag-in-current-line ()
  126.   "Searches tags from the `(point)' to the beginning of the line.
  127. It returns nil, if there is no tag and the tag name, if there is
  128. a tag. The tag name contains a leading /, if it is an end tag."
  129.   (when (re-search-backward ">" (hm--html-return-beginning-of-line) t)
  130.     (when (re-search-backward
  131.        "\\(<[ \t\n]*\\(/?\\)\\([ \t\n]*[^> \t\n]+\\)[^>]*\\)"
  132.        nil
  133.        t)
  134.       (concat (match-string 2) (match-string 3)))))
  135.  
  136. (defun hm--html-search-start-tag (tag-name until)
  137.   "Searches start tag backwards from the current point until the point UNTIL.
  138. The name of the tag is TAG-NAME. After this function the point is at UNTIL
  139.  (then it returns nil) or at the start of the tag, then it returns t."
  140.   (if (re-search-backward (concat "\\(<[ \t\n]*\\)\\(/?\\)\\("
  141.                   tag-name 
  142.                   "\\)\\([^>]*>\\)") until t)
  143.       (if (string= "/" (match-string 2))
  144.       (progn
  145.         (hm--html-search-start-tag tag-name until)
  146.         (hm--html-search-start-tag tag-name until)) 
  147.     t)
  148.     (goto-char until)
  149.     nil))
  150.  
  151. (defun hm--html-is-one-element-tag-p (tag-name)
  152.   "Returns t, if the tag with the tag-name is a one element tag."
  153.   (assoc ':hm--html-one-element-tag
  154.      (cdr (assoc* (downcase tag-name)
  155.               hm--html-tag-name-alist
  156.               :test 'string=))))
  157.  
  158. (defun hm--html-calculate-indent-according-to-previous-tags ()
  159.   "Calculate the indent according to the previous tags in this line.
  160. If no tags are found, then nil is returned."
  161.   (save-excursion
  162.     (let ((tag (hm--html-search-previous-tag-in-current-line)))
  163.       (cond ((not tag) nil)
  164.         
  165.         ((eq ?/ (elt tag 0)) ; end tag found
  166.          (if (hm--html-search-start-tag 
  167.           (substring tag 1)
  168.           (point-min))
  169.          (or (hm--html-calculate-indent-according-to-previous-tags)
  170.              (progn
  171.                (backward-to-indentation 0)
  172.                (current-column)))
  173.            0)) ; it may be that the current indentation is better here
  174.  
  175.         ((hm--html-is-one-element-tag-p tag) ; one element tag
  176.          (or (hm--html-calculate-indent-according-to-previous-tags)
  177.          (progn
  178.            (backward-to-indentation 0)
  179.            (current-column))))
  180.  
  181.         (t ; start tag found
  182.          (+ (current-column) hm--html-inter-tag-indent))))))
  183.  
  184.  
  185. (defun hm--html-calculate-indent ()
  186.   "Calculate the indentation of the current line."
  187.   (let ((match-point)
  188.     (tag))
  189.     (save-excursion
  190.       (beginning-of-line)
  191.       (back-to-indentation)
  192.       (cond ((eq (count-lines (point-min) (point)) 0) 0) ; Filestart
  193.         
  194.         ((setq match-point (hm--html-in-comment-p)) ; in a comment
  195.          (if (>= match-point (hm--html-previous-line-start)) ; 1. line
  196.          (if (hm--html-look-at-comment-end-p)
  197.              (hm--html-column-of-previous-regexp
  198.               (regexp-quote comment-start))
  199.            (+ (hm--html-column-of-previous-regexp
  200.                (regexp-quote comment-start))
  201.               hm--html-comment-indent))
  202.            (if (hm--html-look-at-comment-end-p)
  203.            (- (hm--html-previous-line-indentation)
  204.               hm--html-comment-indent)
  205.          (hm--html-previous-line-indentation))))
  206.         
  207.         ((setq tag (hm--html-look-at-end-tag-p)) ; look at end tag
  208.          (hm--html-search-start-tag tag (point-min))
  209.          (current-column))
  210.         
  211.         ((looking-at ">")
  212.          (hm--html-column-of-previous-regexp "<"))
  213.  
  214.         ((setq match-point (hm--html-in-tag-p))
  215.          (if (>= match-point (hm--html-previous-line-start)) ; 1. line
  216.          (or (hm--html-paramter-column-in-line-after-point match-point)
  217.              (+ (hm--html-column-of-point match-point)
  218.             hm--html-intra-tag-indent))
  219.            (hm--html-previous-line-indentation)))
  220.  
  221.         (t (or (save-excursion  ; check previous line
  222.              (skip-chars-backward " \t\n")
  223.              (hm--html-calculate-indent-according-to-previous-tags))
  224.            (hm--html-previous-line-indentation)))
  225.         ))))
  226.  
  227.  
  228. ;;; Indentation commands
  229.  
  230. (defun hm--html-indent-line ()
  231.   "Indent the current line line."
  232.   (interactive)
  233.   (unless hm--html-disable-indentation
  234.     (let ((pos (- (point-max) (point))))
  235.       (indent-line-to (max 0 (hm--html-calculate-indent)))
  236.       (when (> (- (point-max) pos) (point))
  237.     (goto-char (- (point-max) pos))))))
  238.  
  239. ;(defun hm--html-indent-region (begin end)
  240. ;  "Indents the region between BEGIN and END according to the major mode."
  241. ;  (interactive "d\nm")
  242. ;  (when (< end begin)
  243. ;    (let ((a end))
  244. ;      (setq end begin)
  245. ;      (setq begin a)))
  246. ;  (save-excursion
  247. ;    (goto-char begin)
  248. ;    (let ((old-point))
  249. ;      (while (and (<= (point) end)
  250. ;          (not (eq (point) old-point)))
  251. ;    (setq old-point (point))
  252. ;    (indent-according-to-mode)
  253. ;    (forward-line)
  254. ;    ))))
  255.  
  256. (defun hm--html-indent-region (begin end)
  257.   "Indents the region between BEGIN and END according to the major mode."
  258.   (interactive "d\nm")
  259.   (when (< end begin)
  260.     (let ((a end))
  261.       (setq end begin)
  262.       (setq begin a)))
  263.   (let ((lines (count-lines begin end)))
  264.     (save-excursion
  265.       (goto-char begin)
  266.       (loop repeat lines
  267.             do (indent-according-to-mode)
  268.             (forward-line))))
  269.   )
  270.  
  271. (provide 'hm--html-indentation)
  272.